<#assign
        packageModel=projPackage.projPackage + "." + projPackage.entity
        packageService=projPackage.projPackage + "." + projPackage.service
        exampleClassAndPackage=projPackage.projPackage+"." + projPackage.utils + ".Example"
        >

package ${packageService};

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import ${packageModel}.${billInfo.billClass};
import ${packageModel}.${billInfo.detailClass};
import ${packageModel}.${billInfo.mainClass};
import ${packageService}.BillCodeService;
import ${packageService}.${billInfo.billClass}Service;
import ${packageService}.${billInfo.detailClass}Service;
import ${packageService}.${billInfo.mainClass}Service;
import ${exampleClassAndPackage};

/**
 * 版本号：20240401
 * 默认设置：
 * 1. 主表、明细表主键字段为 id，以及相关的 getter,setter 方法
 * 2. 明细表关联到主表的外键字段 parent_id
 * 3. 主表、明细表主键字段MYSQL数据类型是 bigint，java类型是 Long
 * 4. 默认主表单据编号字段 bill_code
 * 5. 项目数据库中保存单据编号规则的表是 bill_code
 * 6. 代码生成器前端需要构建的参数对象：
 * 7. {"billClass":"BillFabContract","mainClass":"FabContactMain","detailClass":"FabContactDetail","billRemark":"单据描述"}
 */
@Service
public class ${billInfo.billClass}ServiceImpl implements ${billInfo.billClass}Service {
    @Lazy
    @Autowired
    private ${billInfo.mainClass}Service mainService;
    @Lazy
    @Autowired
    private ${billInfo.detailClass}Service detailService;
    @Lazy
    @Autowired
    private ${billInfo.billClass}ServiceImpl meService;
    @Autowired
    private BillCodeService billCodeService;

    private static final String BILL_TYPE = "fab_contract";// 设备维保单据

    @Transactional
    @Override
    public int delete(Long id){
        List<${billInfo.detailClass}> detailList = detailService.selectByExample(new Example().andEq("parent_id", id));
        if(detailList != null && detailList.size() > 0){
            detailList.forEach(item -> detailService.deleteByPrimaryKey(item.getId()));
        }

        mainService.deleteByPrimaryKey(id);
        return 1;
    }

    /**
     * 主表没有主键则所有明细都为新增，主表有主键要检测每个明细数据
     * 有明细主键的则修改，没有的则新增
     * @param record
     * @return
     */
    @Transactional
    @Override
    public ${billInfo.billClass} save(${billInfo.billClass} record) {
        Long idOrigin = Optional.ofNullable(record.getMain().getId()).orElse(Long.valueOf(0));
        record = meService.fullFill(record);

        List<${billInfo.detailClass}> detailList = record.getDetailList();
        Boolean hasDetail = detailList != null && detailList.size() > 0 ? true:false;

        // 新增
        if(idOrigin == 0){
            meService.doBeforeInsert(record);
            if(hasDetail){
                // 清除所有明细主键 - 兼容复制单据
                for (${billInfo.detailClass} item: detailList){
                    item.setId(null);
                }
            }
            // 新增模式下填充单据编号
            record.setMain(fullBillCode(record.getMain()));
        }

        // 执行保存逻辑
        ${billInfo.mainClass} main = mainService.save(record.getMain());
        Long id = main.getId();
        if(hasDetail){
            for (${billInfo.detailClass} item: detailList){
                item.setParentId(id);
            }
            detailList = detailService.multiSave(detailList);
            record.setDetailList(detailList);
        }
        record.setMain(main);

        // 新增状态下调用 doAfterInsert
        if(idOrigin == 0)
            meService.doAfterInsert(record);
        return record;
    }

    @Override
    public ${billInfo.billClass} fullFill(${billInfo.billClass} record){

    }

    // 新增状态下调用本方法，填充单据编号
    private ${billInfo.mainClass} fullBillCode(${billInfo.mainClass} mainRecord){
        billCode = billCodeService.getNewBillCode(BILL_TYPE);
        mainRecord.setBillCode(billCode);
        return mainRecord;
    }

    @Override
    public void doBeforeInsert(${billInfo.billClass} record) {
    }

    @Override
    public void doAfterInsert(${billInfo.billClass} record) {
    }

    @Override
    public ${billInfo.billClass} selectByPrimaryKey(Long id){
        ${billInfo.mainClass} main = mainService.selectByPrimaryKey(id);
        List<${billInfo.detailClass}> detailList = detailService.selectByParentId(id);
        return ${billInfo.billClass}.builder().main(main).detailList(detailList).build();
    }

    public List<${billInfo.detailClass}> getDetailList8PrimaryKey(List<Long> idList){
        return idList.stream().map(detailId -> detailService.selectByPrimaryKey(detailId)).collect(Collectors.toList());
    }

    @Override
    public ${billInfo.billClass} moveBill(Long id, String moveBillFlag){
        ${billInfo.mainClass} mainRecord = mainService.moveBill(id, moveBillFlag);
        if(mainRecord == null) return null;
        List<${billInfo.detailClass}> detailList = detailService.selectByParentId(mainRecord.getId());
        return ${billInfo.billClass}.builder().main(mainRecord).detailList(detailList).build();
    }
}
